package com.itheima.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.pojo.Attendance;
import com.itheima.pojo.AttendanceConfig;
import com.itheima.pojo.Result;
import com.itheima.service.AttendanceConfigService;
import com.itheima.service.AttendanceService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.time.Duration;
import java.time.LocalTime;
import java.time.format.DateTimeParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/attendanceConfig")
public class AttendanceConfigController {

    @Autowired
    private AttendanceService attendanceService;
    @Autowired
    private AttendanceConfigService attendanceConfigService;

    @PostMapping("/updateAllAttendance")
    public Result updateAllAttendance(@RequestBody AttendanceConfig attendanceConfig) {
        // 获取前端传递的上班时间和下班时间
        String morningStartTime = attendanceConfig.getMorningStartTime();
        String afternoonEndTime = attendanceConfig.getAfternoonEndTime();
        String attendceBonus = attendanceConfig.getAttendceBonus();
        // 查询并更新考勤配置表的数据
        AttendanceConfig existingConfig = attendanceConfigService.getById(1L);
        if (existingConfig == null) {
            // 如果没有找到配置，创建一个新的
            existingConfig = new AttendanceConfig();
            existingConfig.setMorningStartTime(morningStartTime);
            existingConfig.setAfternoonEndTime(afternoonEndTime);
            existingConfig.setAttendceBonus(attendceBonus);
            attendanceConfigService.save(existingConfig);  // 如果没有记录则保存新的配置
        } else {
            // 更新现有配置
            existingConfig.setMorningStartTime(morningStartTime);
            existingConfig.setAfternoonEndTime(afternoonEndTime);
            existingConfig.setAttendceBonus(attendceBonus);
            attendanceConfigService.updateById(existingConfig);  // 更新配置
        }
        // 查询数据库中所有员工的考勤记录
        List<Attendance> allAttendance = attendanceService.list();

        // 循环遍历所有员工的考勤记录
        for (Attendance att : allAttendance) {
            // 获取员工的签到时间和签退时间
            String checkinTime = att.getCheckinTime();
            String checkoutTime = att.getCheckoutTime();

            // 根据考勤记录和前端传来的上班时间、下班时间来计算考勤状态
            Integer status = calculateAttendanceStatus(morningStartTime, afternoonEndTime, checkinTime, checkoutTime);

            // 更新考勤状态
            att.setStatus(status);

            // 更新考勤记录
            attendanceService.updateById(att);  // 使用 updateById 来更新考勤记录
        }

        // 返回成功的响应
        return Result.success("所有员工的考勤状态已更新");
    }

    // 计算考勤状态的逻辑
    private Integer calculateAttendanceStatus(String morningStartTime, String afternoonEndTime, String checkinTime, String checkoutTime) {
        // 解析时间
        LocalTime morningStart = parseTime(morningStartTime);
        LocalTime afternoonEnd = parseTime(afternoonEndTime);
        LocalTime checkin = parseTime(checkinTime);
        LocalTime checkout = parseTime(checkoutTime);

        // 如果没有签到时间或者签退时间，视为旷工
        if (checkin == null || checkout == null) {
            return 4; // 旷工
        }

        // 判断迟到
        boolean isLate = checkin.isAfter(morningStart);

        // 判断早退
        boolean isEarlyLeave = checkout.isBefore(afternoonEnd);
        // 判断迟到
        if (isLate) {
            return 2; // 迟到
        }

        // 判断早退
        if (isEarlyLeave) {
            return 3; // 早退
        }
        // 判断同时迟到和早退
        if (isLate && isEarlyLeave) {
            return 5; // 异常（同时迟到和早退）
        }
        // 正常考勤
        return 1; // 正常
    }


    // 时间解析方法，带有异常处理
    private LocalTime parseTime(String timeStr) {
        try {
            if (timeStr != null) {
                return LocalTime.parse(timeStr);
            }
        } catch (DateTimeParseException e) {
            // 解析失败，返回 null
            return null;
        }
        return null;
    }

    // 查询当前考勤配置
    @GetMapping("/getAttendanceConfig")
    public Result getAttendanceConfig() {
        // 假设只有一条记录，根据 ID 查询
        AttendanceConfig config = attendanceConfigService.getById(1L); // 根据实际情况调整查询条件

        if (config == null) {
            return Result.error("考勤配置未找到");
        }

        // 返回成功响应
        return Result.success(config);
    }

    @GetMapping("/getAttendanceConfigList")
    public Result getAttendanceConfigList() {
        List<AttendanceConfig> configList = attendanceConfigService.list(); // 获取所有考勤配置数据
        return Result.success(configList); // 直接返回实体列表，不需要手动映射
    }

    @PostMapping("/updateAttendanceConfig")
    public Result updateAttendanceConfig(@RequestBody List<AttendanceConfig> updatedConfigs) {
        int successCount = 0;
        for (AttendanceConfig updatedConfig : updatedConfigs) {
            AttendanceConfig existingConfig = attendanceConfigService.getById(updatedConfig.getId());
            if (existingConfig == null) {
                continue;
            }

            // 使用 BeanUtils 的 copyProperties 方法，将前端传来的更新后的考勤配置对象的属性值
            // 复制到从数据库中查询出的现有考勤配置对象上，排除id属性，避免覆盖
            BeanUtils.copyProperties(updatedConfig, existingConfig, "id");

            boolean updateSuccess = attendanceConfigService.updateById(existingConfig);
            // 如果更新成功，将成功计数加1
            if (updateSuccess) {
                successCount++;
            }
        }

        // 根据更新成功的数量返回不同的结果信息
        if (successCount == updatedConfigs.size()) {
            return Result.success("考勤配置全部更新成功");
        } else if (successCount > 0) {
            return Result.success("部分考勤配置更新成功，成功更新数量：" + successCount);
        } else {
            return Result.error("考勤配置更新失败");
        }
    }

    //计算月度扣款
    @GetMapping("/calculateDeduction")
    public Result calculateDeduction(@RequestParam Integer employeeId, @RequestParam String month) {
        // 获取所有的考勤配置数据
        List<AttendanceConfig> configList = attendanceConfigService.list();

        // 根据员工 ID 和月份查询该员工的考勤记录
        List<Attendance> attendanceRecords = attendanceService.getRecordsByEmployeeAndMonth(employeeId, month);

        // 用于存储总扣款金额
        BigDecimal totalDeduction = BigDecimal.ZERO;
        for (Attendance record : attendanceRecords) {
            for (AttendanceConfig config : configList) {
                if (config.getIsEnable() == 1) {
                    if ("1".equals(config.getDedTypeCode()) && record.getStatus() == 2) {
                        totalDeduction = totalDeduction.add(calculateDeductionForAttendance(record, config, "late"));
                    } else if ("2".equals(config.getDedTypeCode()) && record.getStatus() == 3) {
                        totalDeduction = totalDeduction.add(calculateDeductionForAttendance(record, config, "earlyLeave"));
                    } else if ("3".equals(config.getDedTypeCode()) && record.getStatus() == 4) {
                        totalDeduction = totalDeduction.add(calculateAbsenceDeduction(record, config));
                    }
                    else if ("1".equals(config.getDedTypeCode()) && record.getStatus() == 5) {
                        // 异常（迟到和早退）扣款 - 迟到部分
                        totalDeduction = totalDeduction.add(calculateDeductionForAttendance(record, config, "late"));
                    } else if ("2".equals(config.getDedTypeCode()) && record.getStatus() == 5) {
                        // 异常（迟到和早退）扣款 - 早退部分
                        totalDeduction = totalDeduction.add(calculateDeductionForAttendance(record, config, "earlyLeave"));
                    }
                }
            }
        }
        // 返回计算得到的总扣款金额
        return Result.success(totalDeduction);
    }

    // 公共扣款计算方法（用于迟到和早退）
    private BigDecimal calculateDeductionForAttendance(Attendance record, AttendanceConfig config, String deductionType) {
        BigDecimal deduction = BigDecimal.ZERO;

        // 根据扣款类型来判断是迟到还是早退，并计算对应的分钟数
        int minutes = 0;
        if ("late".equals(deductionType)) {
            minutes = calculateLateMinutes(record.getCheckinTime(), config.getMorningStartTime());
        } else if ("earlyLeave".equals(deductionType)) {
            minutes = calculateEarlyLeaveMinutes(record.getCheckoutTime(), config.getAfternoonEndTime());
        }
                if (minutes <= Integer.parseInt(config.getPeriodUpperLimit())) {
                    // 对应扣款金额上限
                    deduction = new BigDecimal(config.getDedPeriodUpper());
                } else if(minutes > Integer.parseInt(config.getPeriodLowerLimit())){
                    // 对应扣款金额下限
                    deduction = new BigDecimal(config.getDedPeriodLower());
                }
        return deduction;
    }

    // 计算旷工扣款
    private BigDecimal calculateAbsenceDeduction(Attendance record, AttendanceConfig config) {
        BigDecimal deduction = BigDecimal.ZERO;

        // 检查是否存在旷工情况
        if (record.getStatus() == 4) {
            // 如果是旷工，则按规定金额进行扣款
            deduction = new BigDecimal(config.getDedAbsence());
        }

        return deduction;
    }

    // 计算迟到的分钟数
    private int calculateLateMinutes(String checkinTime, String morningStartTime) {
        try {
            // 将考勤记录的签到时间与规定的上班时间转换为 LocalTime 对象
            LocalTime checkin = LocalTime.parse(checkinTime);
            LocalTime morningStart = LocalTime.parse(morningStartTime);

            // 计算两者之间的时间差，返回其分钟数的绝对值
            return (int) Math.abs(Duration.between(morningStart, checkin).toMinutes());
        } catch (DateTimeParseException e) {
            return 0; // 如果时间格式无效，则返回0分钟
        }
    }

    // 计算早退的分钟数
    private int calculateEarlyLeaveMinutes(String checkoutTime, String afternoonEndTime) {
        try {
            // 将考勤记录的退勤时间与规定的下班时间转换为 LocalTime 对象
            LocalTime checkout = LocalTime.parse(checkoutTime);
            LocalTime afternoonEnd = LocalTime.parse(afternoonEndTime);

            // 计算两者之间的时间差，返回其分钟数的绝对值
            return (int) Math.abs(Duration.between(checkout, afternoonEnd).toMinutes());
        } catch (DateTimeParseException e) {
            return 0; // 如果时间格式无效，则返回0分钟
        }
    }
    @GetMapping("/calculateFullAttendanceBonus")
    public Result calculateFullAttendanceBonus(@RequestParam Integer employeeId, @RequestParam String month) {
        // 获取所有的考勤配置数据
        List<AttendanceConfig> configList = attendanceConfigService.list();

        // 判断配置是否存在，避免索引越界
        if (configList.isEmpty()) {
            return Result.error("不存在的配置");
        }

        // 获取全勤奖金额（来自考勤配置的第一条记录）
        String attendanceBonusStr = configList.get(0).getAttendceBonus();

        // 将字符串类型的全勤奖金额转换为 BigDecimal
        BigDecimal fullAttendanceBonus = null;
        try {
            fullAttendanceBonus = new BigDecimal(attendanceBonusStr);
        } catch (NumberFormatException e) {
            return Result.error("全勤奖类型错误");
        }

        // 根据员工 ID 和月份查询该员工的考勤记录
        List<Attendance> attendanceRecords = attendanceService.getRecordsByEmployeeAndMonth(employeeId, month);

        // 判断是否全勤
        boolean isFullAttendance = true;

        // 遍历每一条考勤记录，检查状态是否都是“1”
        for (Attendance record : attendanceRecords) {
            if (record.getStatus() != 1) {
                isFullAttendance = false;
                break;
            }
        }
        // 如果是全勤，返回全勤奖
        if (isFullAttendance) {
            return Result.success(fullAttendanceBonus);
        } else {
            return Result.success("无法获得全勤奖");
        }
    }
}
